package cn.iocoder.yudao.module.ym.service.site;

import cn.hutool.core.lang.Pair;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.api.area.dto.AreaDto;
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.infra.api.ymconnection.dto.ConnectionRespDto;
import cn.iocoder.yudao.module.infra.enums.DictDataConstants;
import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper;
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper;
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.ym.dal.dataobject.area.AreaDO;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
import cn.iocoder.yudao.module.system.dal.mysql.dict.DictDataMapper;
import cn.iocoder.yudao.module.ym.dal.dataobject.area.AreaDO;
import cn.iocoder.yudao.module.ym.dal.dataobject.connection.ConnectionDO;
import cn.iocoder.yudao.module.ym.dal.dataobject.site.SimpleSiteDO;
import cn.iocoder.yudao.module.ym.dal.dataobject.sitelog.SiteLogDO;
import cn.iocoder.yudao.module.ym.dal.dataobject.ticket.TicketDO;
import cn.iocoder.yudao.module.ym.dal.mysql.area.AreaMapper;
import cn.iocoder.yudao.module.ym.dal.mysql.connection.ConnectionMapper;
import cn.iocoder.yudao.module.ym.dal.mysql.sitelog.SiteLogMapper;
import cn.iocoder.yudao.module.ym.dal.mysql.ticket.TicketMapper;
import cn.iocoder.yudao.module.ym.util.PolygonChecker;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.mzt.logapi.context.LogRecordContext;
import com.mzt.logapi.service.impl.DiffParseFunction;
import com.mzt.logapi.starter.annotation.LogRecord;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.awt.geom.Point2D;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import cn.iocoder.yudao.module.ym.controller.admin.site.vo.*;
import cn.iocoder.yudao.module.ym.dal.dataobject.site.SiteDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.ym.dal.mysql.site.SiteMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.infra.enums.SiteStatusEnum.OPPORTUNITY;
import static cn.iocoder.yudao.module.system.enums.LogRecordConstants.*;

/**
 * 电站 Service 实现类
 *
 * @author 韩艳阳
 */
@Service
@Validated
public class SiteServiceImpl implements SiteService {

    private static final double EARTH_RADIUS = 6371000; // 地球半径，单位米（WGS-84）
    private static final DecimalFormat df = new DecimalFormat("0.######"); // 6位小数格式

    @Resource
    private SiteMapper siteMapper;

    @Resource
    private AreaMapper areaMapper;

    @Resource
    private DictDataMapper dictDataMapper;

    @Resource
    private ConnectionMapper connectionMapper;

    @Resource
    private UserRoleMapper userRoleMapper;

    @Resource
    private RoleMapper roleMapper;

    @Resource
    private RoleMenuMapper roleMenuMapper;

    @Resource
    private AdminUserService adminUserService;

    @Resource
    private AdminUserMapper adminUserMapper;

    @Resource
    private ConfigApi configApi;

    @Resource
    private TicketMapper ticketMapper;

    @Resource
    private SiteLogMapper siteLogMapper;

    @Resource
    private DeptMapper deptMapper;



    @Override
    public String getNames(String ids) {
        List<SiteDO> siteDOS = siteMapper.selectList();
        String names = "";
        if(ids != null && !"".equals(ids) ){
            for (String s : ids.split(",")) {
                if(siteDOS!= null && !siteDOS.isEmpty()){
                    for (SiteDO siteDO : siteDOS) {
                        if(Long.parseLong(s) == siteDO.getId()){
                            names = names + siteDO.getSiteName() + ",";
                        }
                    }
                }
            }
            if(!names.isEmpty()){
                names = names.substring(0,names.length()-1);
            }
        }
        return names;
    }

    @Override
    public String getNames(List<Long> siteIds) {
        List<SiteDO> siteDOS = siteMapper.selectList(new LambdaQueryWrapper<SiteDO>()
                .in(SiteDO::getId,siteIds));
        String names = "";

        if (siteDOS != null && !siteDOS.isEmpty()) {

            for (SiteDO siteDO : siteDOS) {

                names = names + siteDO.getSiteName() + ",";

            }
        }
        return names;
    }

    @Override
    public SiteDO getIdByName(String name) {
        return siteMapper.selectOne(new LambdaQueryWrapper<SiteDO>().eq(SiteDO::getSiteName, name));
    }

    @Override
    @Transactional
    @LogRecord(type = YM_SITE_TYPE, subType = YM_SITE_CREATE_SUB_TYPE, bizNo = "{{#site.id}}",
            success = YM_SITE_CREATE_SUCCESS)
    public Long createSite(SiteSaveReqVO createReqVO) {

        SiteDO siteDO = siteMapper.selectOne(new LambdaQueryWrapper<SiteDO>().eq(SiteDO::getSiteName, createReqVO.getSiteName()));
        if(siteDO!=null){
            throw exception(SITE_EXISTS);
        }

        if (createReqVO.getSiteStatus() != null && createReqVO.getSiteStatus().equals(OPPORTUNITY.getCode())) {
            createReqVO.setBusinessTime(LocalDateTime.now());
        }
        // 插入默认电站icon
        String ymUserAvatar = configApi.getConfigValueByKey("ym_site_image");
        if(createReqVO.getSiteIcon() == null || createReqVO.getSiteIcon().isEmpty()){
            createReqVO.setSiteIcon(ymUserAvatar);
        }

        // 插入
        SiteDO site = BeanUtils.toBean(createReqVO, SiteDO.class);
        siteMapper.insert(site);


        // 3. 记录操作日志上下文
        LogRecordContext.putVariable("site", site);

        // 返回
        return site.getId();
    }

    @Override
    @Transactional
    @LogRecord(type = YM_SITE_TYPE, subType = YM_SITE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
            success = YM_SITE_UPDATE_SUCCESS)
    public void updateSite(SiteSaveReqVO updateReqVO) {
        // 校验存在
        Long siteId = updateReqVO.getId();
        SiteDO oldSiteDO = validateSiteExists(siteId);
        SiteDO siteDO = siteMapper.selectOne(new LambdaQueryWrapper<SiteDO>()
                .eq(SiteDO::getSiteName,updateReqVO.getSiteName())
                .ne(SiteDO::getId,updateReqVO.getId())
                .last("LIMIT 1"));
        if (siteDO != null) {
            throw exception(SITE_NAME_ALREADY_EXISTS);
        }

        /*SiteDO siteDO = siteMapper.selectOne(new LambdaQueryWrapper<SiteDO>()
                .eq(SiteDO::getSiteName,updateReqVO.getSiteName())
                .ne(SiteDO::getId,updateReqVO.getId())
                .last("LIMIT 1"));
        if (siteDO != null) {
            throw exception(SITE_NAME_ALREADY_EXISTS);
        }
        //获取原来绑定在此电站的用户
        List<Long> oldUserIds = new ArrayList<>();
        List<ConnectionDO> connectionDOS1 = connectionMapper.selectList(new LambdaQueryWrapper<ConnectionDO>()
                .eq(ConnectionDO::getThingId,siteId)
                .eq(ConnectionDO::getType,2));
        for (ConnectionDO connectionDO : connectionDOS1) {
            Long userId = connectionDO.getPeopleId();
            oldUserIds.add(userId);
        }
        //获取新绑定在此电站的用户
        List<Long> newUserIds = updateReqVO.getBoundUserIds();
        //增加的人
        List<Long> addUserIds = new ArrayList<>(newUserIds);
        addUserIds.removeAll(oldUserIds);
        //减少的人
        List<Long> deleteUserIds = new ArrayList<>(oldUserIds);
        deleteUserIds.removeAll(newUserIds);
        //增加关联表中的内容
        if (addUserIds!= null && !addUserIds.isEmpty()) {
            for (Long addUserId : addUserIds) {
                ConnectionDO connectionDO1 = new ConnectionDO();
                connectionDO1.setPeopleId(addUserId);
                connectionDO1.setThingId(siteId);
                connectionDO1.setType(2);
                connectionMapper.insert(connectionDO1);
            }
        }
        //删除关联表中的内容
        if (deleteUserIds!= null && !deleteUserIds.isEmpty()) {
            List<ConnectionDO> connectionDOS2 = connectionMapper.selectList(new LambdaQueryWrapper<ConnectionDO>()
                    .eq(ConnectionDO::getThingId,siteId)
                    .in(ConnectionDO::getPeopleId,deleteUserIds)
                    .eq(ConnectionDO::getType,2));
            for (ConnectionDO connectionDO : connectionDOS2) {
                connectionMapper.deleteById(connectionDO);
            }
        }*/
        // 更新
        SiteDO updateObj = BeanUtils.toBean(updateReqVO, SiteDO.class);
        siteMapper.updateById(updateObj);

        // 3. 记录操作日志上下文
        LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldSiteDO, SiteSaveReqVO.class));
        LogRecordContext.putVariable("site", oldSiteDO);
    }

    @Override
    @Transactional
    @LogRecord(type = YM_SITE_TYPE, subType = YM_SITE_DELETE_SUB_TYPE, bizNo = "{{#id}}",
            success = YM_SITE_DELETE_SUCCESS)
    public void deleteSite(Long id) {
        // 校验存在
        SiteDO siteDO = validateSiteExists(id);
        //获取当前电站在关联表的数据
        List<ConnectionDO> connectionDOS = connectionMapper.selectList(new LambdaQueryWrapper<ConnectionDO>()
                .eq(ConnectionDO::getThingId,id)
                .eq(ConnectionDO::getType,2));

        //批量删除
        if(connectionDOS != null && !connectionDOS.isEmpty()){
            Set<Long> collect = connectionDOS.stream().map(ConnectionDO::getId).collect(Collectors.toSet());
            connectionMapper.deleteByIds(collect);
        }

        //判断电站下是否有工单，若有工单则不让删除 todo 有可能改为未完成工单
        List<TicketDO> ticketDOS = ticketMapper.selectList(new LambdaQueryWrapper<TicketDO>()
                .eq(TicketDO::getSiteId,id));

        if (ticketDOS != null && !ticketDOS.isEmpty()) {
            throw exception(SITE_WORK_ORDER_EXISTS);
        }

        // 删除
        siteMapper.deleteById(id);
        //加入日志
        LogRecordContext.putVariable("site", siteDO);

    }

    private SiteDO validateSiteExists(Long id) {
        SiteDO siteDO = siteMapper.selectById(id);
        if (siteDO == null) {
            throw exception(SITE_NOT_EXISTS);
        }
        return siteDO;
    }

    @Override
    public SiteRespVO getSite(Long id) {
        SiteRespVO siteRespVO = BeanUtils.toBean(siteMapper.selectById(id), SiteRespVO.class);
        if(siteRespVO != null){
            List<SiteLogDO> siteLogDOS = siteLogMapper.selectList(new LambdaQueryWrapper<SiteLogDO>().eq(SiteLogDO::getSiteId, siteRespVO.getId()));
            siteRespVO.setSiteLogDOList(siteLogDOS);
        }
        /*List<Long> oldUserIds = new ArrayList<>();
        List<ConnectionDO> connectionDOS1 = connectionMapper.selectList(new LambdaQueryWrapper<ConnectionDO>()
                .eq(ConnectionDO::getThingId,id)
                .eq(ConnectionDO::getType,2));
        for (ConnectionDO connectionDO : connectionDOS1) {
            Long userId = connectionDO.getPeopleId();
            oldUserIds.add(userId);
        }*/
       /* siteRespVO.setBoundUserIds(oldUserIds);
        List<AdminUserDO> adminUserDOS = adminUserMapper.selectByIds(oldUserIds);

        List<String> userNames = new ArrayList<>();
        for (AdminUserDO adminUserDO : adminUserDOS) {
            userNames.add(adminUserDO.getNickname());
        }
        siteRespVO.setBoundUserNames(userNames);
*/
        return siteRespVO;
    }


    @Override
    public PageResult<SiteRespVO> getSitePage(SitePageReqVO pageReqVO) {
        Long loginUserId = getLoginUserId();
        Long userId = pageReqVO.getUserId();

        if(userId != null){
            loginUserId = userId;
        }

        //判断有没有使用公司搜索
        Long deptId = pageReqVO.getDeptId();
        if(deptId != null){
            DeptDO deptDO = deptMapper.selectById(deptId);
            if(deptDO != null){
                loginUserId = deptDO.getLeaderUserId();
            }
        }

        //查看当前用户是否有查看所有数据的权限
        Boolean flag = handleAll(loginUserId);

        PageResult<SiteDO> siteDOPageResult = new PageResult<>();
        Set<Long> siteSet = new HashSet<>();

        List<AreaDO> areaDOList = areaMapper.selectList();
        Map<Long, AreaDO> areaMap = Optional.ofNullable(areaDOList)
                .orElseGet(Collections::emptyList) // 处理null列表
                .stream()
                .filter(areaDo -> areaDo.getId() != null)
                .collect(Collectors.toMap(
                        AreaDO::getId,  // Key提取器
                        Function.identity(),  // Value提取器（对象本身）
                        (oldValue, newValue) -> oldValue  // 处理重复键：保留第一个值
                ));

        if(flag){
            siteDOPageResult = siteMapper.selectPage(pageReqVO);

        }else {
            //查看当前用户是否有查看所有电站的数据权限
            Boolean siteAll = handleSiteAll(loginUserId);

            AdminUserDO user = adminUserService.getUser(loginUserId);
            if(user != null){
                List<ConnectionRespDto> connectionRespDtoList = user.getConnectionRespDtoList();
                if(connectionRespDtoList!= null &&!connectionRespDtoList.isEmpty()){
                    // 按 type 分组，收集 thingId 到 Set<Long>
                    Map<Integer, Set<Long>> grouped = connectionRespDtoList.stream()
                            .filter(Objects::nonNull) // 过滤空对象
                            .filter(dto -> dto.getType() != null && (dto.getType() == 1 || dto.getType() == 2))
                            .filter(dto -> dto.getThingId() != null) // 过滤无效 thingId
                            .collect(Collectors.groupingBy(
                                    ConnectionRespDto::getType,
                                    Collectors.mapping(ConnectionRespDto::getThingId, Collectors.toSet())
                            ));

                    // 提取结果（若没有对应 type，返回空集合）
                    siteSet = grouped.getOrDefault(2, Collections.emptySet());
                }
            }
            if(siteSet!= null &&!siteSet.isEmpty()){
                pageReqVO.setIds(siteSet);
            }
            if(!siteAll && deptId == null){
                pageReqVO.setSiteStatus(DictDataConstants.YM_SITE_STATUS_5);
            }
            siteDOPageResult = siteMapper.selectPage(pageReqVO);
        }
        List<SiteDO> siteDOList = siteDOPageResult.getList();
        if(siteDOList != null && !siteDOList.isEmpty()){
            for (SiteDO siteDO : siteDOList) {
                AreaDO areaDO = areaMap.get(siteDO.getAreaId());
                Optional.ofNullable(areaDO).ifPresent(a -> {
                    siteDO.setAreaName(a.getAreaName());
                });
            }
        }

        return  BeanUtils.toBean(siteDOPageResult, SiteRespVO.class);
    }

    @Override
    public List<SiteRespVO> getSiteListAll(SitePageReqVO pageReqVO) {
        return BeanUtils.toBean(siteMapper.selectList(pageReqVO),SiteRespVO.class);
    }

    @Override
    public List<SiteRespVO> getSiteList(SitePageReqVO pageReqVO) {
        Long loginUserId = getLoginUserId();
        Long userId = pageReqVO.getUserId();

        if(userId != null){
            loginUserId = userId;
        }

        //判断有没有使用公司搜索
        Long deptId = pageReqVO.getDeptId();
        if(deptId != null){
            DeptDO deptDO = deptMapper.selectById(deptId);
            if(deptDO != null){
                loginUserId = deptDO.getLeaderUserId();
            }
        }

        //查看当前用户是否有查看所有数据的权限
        Boolean flag = handleAll(loginUserId);

        List<SiteDO> siteDOList = new ArrayList<>();
        Set<Long> siteSet = new HashSet<>();

        List<AreaDO> areaDOList = areaMapper.selectList();
        Map<Long, AreaDO> areaMap = Optional.ofNullable(areaDOList)
                .orElseGet(Collections::emptyList) // 处理null列表
                .stream()
                .filter(areaDo -> areaDo.getId() != null)
                .collect(Collectors.toMap(
                        AreaDO::getId,  // Key提取器
                        Function.identity(),  // Value提取器（对象本身）
                        (oldValue, newValue) -> oldValue  // 处理重复键：保留第一个值
                ));


        if(flag){
            siteDOList = siteMapper.selectList(pageReqVO);

        }else {
            //查看当前用户是否有查看所有电站的数据权限
            Boolean siteAll = handleSiteAll(loginUserId);

            AdminUserDO user = adminUserService.getUser(loginUserId);
            if(user != null){
                List<ConnectionRespDto> connectionRespDtoList = user.getConnectionRespDtoList();
                if(connectionRespDtoList!= null &&!connectionRespDtoList.isEmpty()){
                    // 按 type 分组，收集 thingId 到 Set<Long>
                    Map<Integer, Set<Long>> grouped = connectionRespDtoList.stream()
                            .filter(Objects::nonNull) // 过滤空对象
                            .filter(dto -> dto.getType() != null && (dto.getType() == 1 || dto.getType() == 2))
                            .filter(dto -> dto.getThingId() != null) // 过滤无效 thingId
                            .collect(Collectors.groupingBy(
                                    ConnectionRespDto::getType,
                                    Collectors.mapping(ConnectionRespDto::getThingId, Collectors.toSet())
                            ));

                    // 提取结果（若没有对应 type，返回空集合）
                    siteSet = grouped.getOrDefault(2, Collections.emptySet());
                }
            }
            if(siteSet!= null &&!siteSet.isEmpty()){
                pageReqVO.setIds(siteSet);
            }
            if(!siteAll && deptId == null){
                pageReqVO.setSiteStatus(DictDataConstants.YM_SITE_STATUS_5);
            }
            siteDOList = siteMapper.selectList(pageReqVO);
        }
        if(siteDOList != null && !siteDOList.isEmpty()){
            for (SiteDO siteDO : siteDOList) {
                AreaDO areaDO = areaMap.get(siteDO.getAreaId());
                Optional.ofNullable(areaDO).ifPresent(a -> {
                    siteDO.setAreaName(a.getAreaName());
                });
            }
        }



        return  BeanUtils.toBean(siteDOList, SiteRespVO.class);
    }

    @Override
    public List<SimpleSiteRespVO> getSimpleSiteList(SitePageReqVO pageReqVO) {
        Long loginUserId = getLoginUserId();
        Long userId = pageReqVO.getUserId();

        if(userId != null){
            loginUserId = userId;
        }

        //判断有没有使用公司搜索
        Long deptId = pageReqVO.getDeptId();
        if(deptId != null){
            DeptDO deptDO = deptMapper.selectById(deptId);
            if(deptDO != null){
                loginUserId = deptDO.getLeaderUserId();
            }
        }

        //查看当前用户是否有查看所有数据的权限
        Boolean flag = handleAll(loginUserId);

        List<SiteDO> siteDOList = new ArrayList<>();
        Set<Long> siteSet = new HashSet<>();

        List<AreaDO> areaDOList = areaMapper.selectList();
        Map<Long, AreaDO> areaMap = Optional.ofNullable(areaDOList)
                .orElseGet(Collections::emptyList) // 处理null列表
                .stream()
                .filter(areaDo -> areaDo.getId() != null)
                .collect(Collectors.toMap(
                        AreaDO::getId,  // Key提取器
                        Function.identity(),  // Value提取器（对象本身）
                        (oldValue, newValue) -> oldValue  // 处理重复键：保留第一个值
                ));


        if(flag){
            siteDOList = siteMapper.selectList(pageReqVO);

        }else {
            //查看当前用户是否有查看所有电站的数据权限
            Boolean siteAll = handleSiteAll(loginUserId);

            AdminUserDO user = adminUserService.getUser(loginUserId);
            if(user != null){
                List<ConnectionRespDto> connectionRespDtoList = user.getConnectionRespDtoList();
                if(connectionRespDtoList!= null &&!connectionRespDtoList.isEmpty()){
                    // 按 type 分组，收集 thingId 到 Set<Long>
                    Map<Integer, Set<Long>> grouped = connectionRespDtoList.stream()
                            .filter(Objects::nonNull) // 过滤空对象
                            .filter(dto -> dto.getType() != null && (dto.getType() == 1 || dto.getType() == 2))
                            .filter(dto -> dto.getThingId() != null) // 过滤无效 thingId
                            .collect(Collectors.groupingBy(
                                    ConnectionRespDto::getType,
                                    Collectors.mapping(ConnectionRespDto::getThingId, Collectors.toSet())
                            ));

                    // 提取结果（若没有对应 type，返回空集合）
                    siteSet = grouped.getOrDefault(2, Collections.emptySet());
                }
            }
            if(siteSet!= null &&!siteSet.isEmpty()){
                pageReqVO.setIds(siteSet);
            }
            if(!siteAll && deptId == null){
                pageReqVO.setSiteStatus(DictDataConstants.YM_SITE_STATUS_5);
            }
            siteDOList = siteMapper.selectList(pageReqVO);
        }
        if(siteDOList != null && !siteDOList.isEmpty()){
            for (SiteDO siteDO : siteDOList) {
                AreaDO areaDO = areaMap.get(siteDO.getAreaId());
                Optional.ofNullable(areaDO).ifPresent(a -> {
                    siteDO.setAreaName(a.getAreaName());
                });
            }
        }



        return  BeanUtils.toBean(siteDOList, SimpleSiteRespVO.class);
    }

    @Override
    public List<SiteRespVO> getSiteByAreaId(Long areaId,Long userId) {
        SitePageReqVO pageReqVO = new SitePageReqVO();
        pageReqVO.setAreaId(areaId);
        //查看当前用户是否有查看所有数据的权限
        Boolean flag = handleAll(userId);

        List<SiteDO> siteDOList = new ArrayList<>();
        Set<Long> siteSet = new HashSet<>();

        List<AreaDO> areaDOList = areaMapper.selectList();
        Map<Long, AreaDO> areaMap = Optional.ofNullable(areaDOList)
                .orElseGet(Collections::emptyList) // 处理null列表
                .stream()
                .collect(Collectors.toMap(
                        AreaDO::getId,  // Key提取器
                        Function.identity(),  // Value提取器（对象本身）
                        (oldValue, newValue) -> oldValue  // 处理重复键：保留第一个值
                ));


        if(flag){
            siteDOList = siteMapper.selectList(pageReqVO);

        }else {
            //查看当前用户是否有查看所有电站的数据权限
            Boolean siteAll = handleSiteAll(userId);

            AdminUserDO user = adminUserService.getUser(userId);
            if(user != null){
                List<ConnectionRespDto> connectionRespDtoList = user.getConnectionRespDtoList();
                if(connectionRespDtoList!= null &&!connectionRespDtoList.isEmpty()){
                    // 按 type 分组，收集 thingId 到 Set<Long>
                    Map<Integer, Set<Long>> grouped = connectionRespDtoList.stream()
                            .filter(Objects::nonNull) // 过滤空对象
                            .filter(dto -> dto.getType() != null && (dto.getType() == 1 || dto.getType() == 2))
                            .collect(Collectors.groupingBy(
                                    ConnectionRespDto::getType,
                                    Collectors.mapping(ConnectionRespDto::getThingId, Collectors.toSet())
                            ));

                    // 提取结果（若没有对应 type，返回空集合）
                    siteSet = grouped.getOrDefault(2, Collections.emptySet());
                }
            }
            if(siteSet!= null &&!siteSet.isEmpty()){
                pageReqVO.setIds(siteSet);
            }
            if(!siteAll){
                pageReqVO.setSiteStatus(DictDataConstants.YM_SITE_STATUS_5);
            }
            siteDOList = siteMapper.selectList(pageReqVO);
        }
        if(siteDOList != null && !siteDOList.isEmpty()){
            for (SiteDO siteDO : siteDOList) {
                AreaDO areaDO = areaMap.get(siteDO.getAreaId());
                Optional.ofNullable(areaDO).ifPresent(a -> {
                    siteDO.setAreaName(a.getAreaName());
                });
            }
        }

        return  BeanUtils.toBean(siteDOList, SiteRespVO.class);
    }


    // 判断当前用户是否 管理员
    public Boolean handleAll(Long userId){
        //判断当前用户得权限  如果是tenant_admin 则查看全部数据
        List<UserRoleDO> userRoleDOS = userRoleMapper.selectListByUserId(userId);
        if(userRoleDOS!= null && !userRoleDOS.isEmpty()){
            for (UserRoleDO userRoleDO : userRoleDOS) {
                Long roleId = userRoleDO.getRoleId();
                RoleDO roleDO = roleMapper.selectById(roleId);
                if(roleDO!=null && roleDO.getCode().equals("tenant_admin")){
                    return true;
                }
            }
        }
        return false;
    }
    // 判断当前用户是否 具有查看所有状态电站的权限
    public Boolean handleSiteAll(Long userId){
        //2807	查看全部电站	yn:site:all
        //2808	查看已上线电站	ym:site_online
        List<UserRoleDO> userRoleDOS = userRoleMapper.selectListByUserId(userId);
        if(userRoleDOS!= null &&!userRoleDOS.isEmpty()){
            for (UserRoleDO userRoleDO : userRoleDOS) {
                Long roleId = userRoleDO.getRoleId();
                RoleDO roleDO = roleMapper.selectById(roleId);
                if(roleDO != null){
                    List<RoleMenuDO> roleMenuDOS = roleMenuMapper.selectListByRoleId(roleDO.getId());
                    if(roleMenuDOS!= null && !roleMenuDOS.isEmpty()){
                        for (RoleMenuDO roleMenuDO : roleMenuDOS) {
                            if(roleMenuDO.getMenuId() == 2807){
                                return true;
                            }
                        }
                    }
                }
            }
        }
        return false;
    }

    @Override
    @Transactional
    @LogRecord(type = YM_SITE_TYPE, subType = YM_SITE_IMPORT_SUB_TYPE, bizNo = "{{1}}",
            success = YM_SITE_IMPORT_SUCCESS)
    public UserImportRespVO importSite(List<SiteImportVO> importVOList, Boolean isUpdateSupport) {

        List<SiteDO> siteDOList = new ArrayList<>();
        List<SiteDO> updateOList = new ArrayList<>();

        List<DictDataDO> dictDataDOS = dictDataMapper.selectList(new LambdaQueryWrapper<DictDataDO>()
                .eq(DictDataDO::getDictType, DictTypeConstants.YM_SUPPORTING_FACILITY));

        Map<String, String> dictMap = dictDataDOS.stream()
                .collect(Collectors.toMap(
                        DictDataDO::getLabel,   // Key提取器
                        DictDataDO::getValue,   // Value提取器
                        (existingValue, newValue) -> newValue // 处理键冲突的合并函数（保留最后一个值）
                ));

        //一些 判断
        isLegal(importVOList);

        //处理导入逻辑
        UserImportRespVO respVO = UserImportRespVO.builder()
                .createUsernames(new ArrayList<>())
                .updateUsernames(new ArrayList<>())
                .failureUsernames(new LinkedHashMap<>()).build();

        List<AreaDO> areaDOList = areaMapper.selectList();
        // 正确转换方式
        Map<String, AreaDO> areaMap = Optional.ofNullable(areaDOList)
                .orElseGet(Collections::emptyList) // 处理null列表
                .stream()
                .filter(areaDO -> areaDO.getAreaName() != null)
                .collect(Collectors.toMap(
                        AreaDO::getAreaName,  // Key提取器
                        Function.identity(),  // Value提取器（对象本身）
                        (oldValue, newValue) -> oldValue  // 处理重复键：保留第一个值
                ));
        List<SiteDO> siteDOS = siteMapper.selectList();
        // 正确转换方式
        Map<String, SiteDO> siteMap = Optional.ofNullable(siteDOS)
                .orElseGet(Collections::emptyList) // siteDOS
                .stream()
                .filter(siteDo -> siteDo.getSiteName() != null)
                .collect(Collectors.toMap(
                        SiteDO::getSiteName,  // Key提取器
                        Function.identity(),  // Value提取器（对象本身）
                        (oldValue, newValue) -> oldValue  // 处理重复键：保留第一个值
                ));
        importVOList.forEach(vo -> {
            try {

                if (vo.getSiteStatus() != null && vo.getSiteStatus().equals(OPPORTUNITY.getCode())) {
                    vo.setBusinessTime(LocalDateTime.now());
                }

                String convert = convert(vo, dictMap);


                //查询他们的区域id
                AreaDO areaDO = areaMap.get(vo.getAreaName());
                if(areaDO == null){
                    respVO.getFailureUsernames().put(vo.getAreaName(), "系统暂无该区域");
                    return;
                }else {
                    vo.setAreaId(areaDO.getId());
                }


                // 唯一性检查（按电站名称）
                SiteDO siteDO = siteMap.get(vo.getSiteName());

                //插入或更新
                if (siteDO == null) {
                    SiteDO bean = BeanUtil.toBean(vo, SiteDO.class);
                    String ymSiteImage = configApi.getConfigValueByKey("ym_site_image");
                    bean.setSiteIcon(ymSiteImage);
                    bean.setSupportingFacilities(convert);
                    siteDOList.add(bean);
                    respVO.getCreateUsernames().add("1");
                } else if (isUpdateSupport) {
                    Long areaId = siteDO.getAreaId(); //之前区域
                    Long nowAreaId = vo.getAreaId(); // 现在区域

                    if(Objects.equals(areaId, nowAreaId)){
                        SiteDO updateDO = BeanUtil.toBean(vo, SiteDO.class);
                        updateDO.setId(siteDO.getId());
                        updateDO.setSupportingFacilities(convert);
                        updateOList.add(updateDO);
//                        respVO.getUpdateUsernames().add(vo.getSiteName());
                        respVO.getUpdateUsernames().add("1");
                    }else {
                        respVO.getFailureUsernames().put(vo.getSiteName(), "区域有变更，请手动更新");
                    }


                } else {
                    respVO.getFailureUsernames().put(vo.getSiteName(), "电站已存在且不允许更新");
                }

            }catch (Exception e){
                respVO.getFailureUsernames().put(vo.getSiteName(), "系统错误: " + e.getMessage());
            }
        });

        if(!siteDOList.isEmpty()){
            siteMapper.insertBatch(siteDOList,5000);
        }
        if(!updateOList.isEmpty()){
            siteMapper.updateBatch(updateOList,5000);
            LogRecordContext.putVariable("site", null);
        }

        return respVO;
    }

    /**
     * 电站导入前的一些格式判断
     * @param importVOList
     */
    private static void isLegal(List<SiteImportVO> importVOList) {
        //是否为空
        if (CollUtil.isEmpty(importVOList)) {
            throw exception(SITE_IMPORT_LIST_IS_EMPTY);
        }
        Map<String, Integer> keyCountMap = new HashMap<>();
        for (SiteImportVO siteImportVO : importVOList) {
            String siteName = siteImportVO.getSiteName();
            if (siteName == null) {
                throw exception(SITE_NAME_NOT_EXISTS);
            }
            if(keyCountMap.get(siteName) != null){
                throw exception(new ErrorCode(1_001_201_033, String.format("EXCEL- %s 电站名字重复",siteName)));
            }
            keyCountMap.put(siteName,1);
            String latitudeLongitude = siteImportVO.getLatitudeLongitude();

            if (latitudeLongitude != null && !latitudeLongitude.isEmpty()) {

                if (!isValidLatitudeLongitude(latitudeLongitude)){
                    throw  exception(LATITUDE_LONGITUDE_ILLEGAL);
                }else {
                    String replace = latitudeLongitude.replace(" ", "");
                    siteImportVO.setLatitudeLongitude(replace);
                }
                Point2D.Double center = convert(latitudeLongitude);
                //经度
                Double x = center.getX();
                String lon = x.toString();
                //纬度
                Double y = center.getY();
                String lat = y.toString();
                String s = generateGeoSquare(x, y, 10);
                siteImportVO.setLon(lon);
                siteImportVO.setLat(lat);
                siteImportVO.setCoordinates(s);
            }else {
                throw exception(LATITUDE_LONGITUDE_NOT_EMPTY);
            }

        }
    }


    //基础设施导入字典转换
    public String convert(SiteImportVO vo,Map dictMap){
        if (vo.getSupportingFacilities() != null && !vo.getSupportingFacilities().isEmpty()) {

            String stream = Arrays.stream(vo.getSupportingFacilities().split("\\|"))
                    .map(key -> dictMap.getOrDefault(key,null))
                    .filter(Objects::nonNull)
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
            return stream;
        }

        return null;

    }


    //自动判断电站是否在区域内并修改数据库内容
    @Override
    @Transactional
    public Pair<List<SiteBindingVO>, List<ConnectionDO>> planningArea(){
        //获取区域和电站表的数据
        Long loginUserId = getLoginUserId();
        List<AreaDO> areaDOS = new ArrayList<>();
        List<SiteDO> siteDOS = new ArrayList<>();
        List<Long> areaIds = new ArrayList<>();
        //若当前登入用户为管理员，则对全部数据进行自动绑定
        if (handleAll(loginUserId)) {
            areaDOS = areaMapper.selectList();
            siteDOS = siteMapper.selectList();
        }else {
            //若为其他人员则之对和自己绑定区域和区域下电站进行更改，为主管，其他人不分配权限
            List<ConnectionDO> connectionDOS1 = connectionMapper.selectList(new LambdaQueryWrapper<ConnectionDO>()
                    .eq(ConnectionDO::getPeopleId,loginUserId)
                    .eq(ConnectionDO::getType,1));
            if (connectionDOS1 == null || connectionDOS1.isEmpty()) {
                throw exception(PEOPLE_NOT_AREA);
            }

            for (ConnectionDO connectionDO : connectionDOS1) {
                Long areaId = connectionDO.getThingId();
                areaIds.add(areaId);
            }
            areaDOS = areaMapper.selectByIds(areaIds);

            siteDOS = siteMapper.selectList(new LambdaQueryWrapper<SiteDO>()
                    .in(SiteDO::getAreaId,areaIds));
            if (siteDOS == null || siteDOS.isEmpty()) {
                throw exception(AREA_NOT_SITE);
            }
        }

        //判断不为空
        if (areaDOS== null || areaDOS.isEmpty()) {
            throw exception(AREA_NOT_EXISTS);
        }
        if (siteDOS== null || siteDOS.isEmpty()) {
            throw exception(SITE_NOT_EXISTS);
        }
        //获取关联数据表中的所有电站的关联数据
        List<ConnectionDO> type2ConnectionDOS = connectionMapper.selectList(new LambdaQueryWrapper<ConnectionDO>()
                .eq(ConnectionDO::getType,2));
        //转为以电站id为key，关联数据list为value的map
        Map<Long,List<ConnectionDO>> type2ConnectionDOSMap = type2ConnectionDOS
                .stream()
                .collect(Collectors.groupingBy(ConnectionDO::getThingId));
        //获取关联数据表中的所有区域的关联数据
        List<ConnectionDO> type1ConnectionDOS = connectionMapper.selectList(new LambdaQueryWrapper<ConnectionDO>()
                .eq(ConnectionDO::getType,1));
        //set使得遍历起来更加快速pair使得区域和人的二者组合唯一
        Set<Pair<Long,Long>> type1ConnectionDOSSet = type1ConnectionDOS
                .stream()
                .map(conn ->Pair.of(conn.getThingId(),conn.getPeopleId()))
                .collect(Collectors.toSet());
        List<SiteDO> siteDOList = new ArrayList<>();
        List<ConnectionDO> connectionDOList = new ArrayList<>();

        List<SiteBindingVO> siteBindingVOList = new ArrayList<>();

        double[] doubles;

        //遍历每一个区域
        for (AreaDO areaDO : areaDOS) {
            //将坐标集合数据转化为list数组

            if (areaDO.getCoordinates() != null && !areaDO.getCoordinates().isEmpty()) {
                //遍历每一个电站
                for (SiteDO siteDO : siteDOS) {
                    //若电站不为空并且电站中心点不为空
                    if (siteDO.getLatitudeLongitude() != null ) {
                        //将电站中心点转化为point2D
                        Point2D.Double point = convertStringToPoint(siteDO.getLatitudeLongitude());

                        double[] pointDouble = convertStringToDoubleArray(siteDO.getLatitudeLongitude());

                        //若电站在区域构成的最大四边形内并且在区域坐标集合内
                        if(PolygonChecker.isPointInAnyPolygon(pointDouble,areaDO.getCoordinates())){
                            //若电站现在在的区域和原来的区域一样则不修改
                            Long oldAreaId = siteDO.getAreaId();
                            Long newAreaId = areaDO.getId();
                            if (Objects.equals(oldAreaId, newAreaId)) {
                                continue;
                            }
                            //将要更新的数据插入到一个新的VO类中，并将其list返回给前端
                            SiteBindingVO siteBindingVO = new SiteBindingVO();
                            siteBindingVO.setId(siteDO.getId());
                            siteBindingVO.setSiteName(siteDO.getSiteName());
                            siteBindingVO.setOldAreaId(oldAreaId);
                            siteBindingVO.setNewAreaId(newAreaId);
                            siteBindingVOList.add(siteBindingVO);

                            siteDO.setAreaId(newAreaId);
                            siteDOList.add(siteDO);
                            //获取当前电站下关联表数据
                           List<ConnectionDO> connectionDOS = type2ConnectionDOSMap
                                   .getOrDefault(siteDO.getId(),Collections.emptyList());
                            if (connectionDOS != null && !connectionDOS.isEmpty()) {
                                for (ConnectionDO connectionDO : connectionDOS) {
                                    Long userId = connectionDO.getPeopleId();
                                    //定义一个pair类型的新区域和人的关联
                                    Pair<Long,Long> key = Pair.of(newAreaId,userId);
                                    //判断原来的set集合里面是否包含这个key，若包含则说明数据库的数据也包含，这样就直接跳过，若不包含则插入数据
                                    if (key != null && !type1ConnectionDOSSet.contains(key)){
                                        ConnectionDO newConnection = new ConnectionDO();
                                        newConnection.setPeopleId(userId);
                                        newConnection.setThingId(newAreaId);
                                        newConnection.setType(1);
                                        connectionDOList.add(newConnection);
                                    }
                            }
                            }
                        }
                    }
                }
            }

        }
        if (siteBindingVOList != null && !siteBindingVOList.isEmpty()) {
            // 1. 构建区域ID到名称的映射（处理重复ID）
            Map<Long, String> areaNameMap = new HashMap<>();
            for (AreaDO areaDO : areaDOS) {
                if (areaDO.getId() != null && areaDO.getAreaName() != null) {
                    areaNameMap.put(areaDO.getId(), areaDO.getAreaName());
                }
            }

            // 2. 设置VO的区域名称（安全处理空值）
            for (SiteBindingVO vo : siteBindingVOList) {
                // 旧区域名称
                if (vo.getOldAreaId() != null) {
                    vo.setOldAreaName(areaNameMap.get(vo.getOldAreaId()));
                }
                // 新区域名称
                if (vo.getNewAreaId() != null) {
                    vo.setNewAreaName(areaNameMap.get(vo.getNewAreaId()));
                }
            }
        }
        List<ConnectionDO> uniqueList = connectionDOList.stream()
                // 组合 peopleId 和 thingId 作为键，过滤 null 值
                .filter(conn -> Objects.nonNull(conn.getPeopleId()) && Objects.nonNull(conn.getThingId()))
                .collect(Collectors.toMap(
                        conn -> new AbstractMap.SimpleEntry<>(conn.getPeopleId(), conn.getThingId()),
                        conn -> conn,
                        // 键冲突时保留第一个元素（或改为 (oldVal, newVal) -> newVal 保留最后一个）
                        (existing, replacement) -> existing
                ))
                .values()
                .stream()
                .collect(Collectors.toList());

        return Pair.of(siteBindingVOList,uniqueList);

    }

    @Override
    @Transactional
    @LogRecord(type = YM_SITE_TYPE, subType = YM_SITE_LOCATION_SUB_TYPE, bizNo = "{{2}}",
            success = YM_SITE_LOCATION_SUCCESS)
    public void confirmPlanningArea(List<SiteBindingVO> siteBindingVOList, List<ConnectionDO> connectionDOList){
        if (siteBindingVOList !=null && !siteBindingVOList.isEmpty()) {

            Map<Long,Long> map = new HashMap<>();
            List<Long> siteIds = new ArrayList<>();
            for (SiteBindingVO siteBindingVO : siteBindingVOList) {
                Long siteId = siteBindingVO.getId();
                Long newAreaId = siteBindingVO.getNewAreaId();
                siteIds.add(siteId);
                map.put(siteId,newAreaId);
            }
            List<SiteDO> siteDOS = siteMapper.selectByIds(siteIds);
            for (SiteDO siteDO : siteDOS) {
                siteDO.setAreaId(map.get(siteDO.getId()));
            }
            siteMapper.updateBatch(siteDOS);
            LogRecordContext.putVariable("site", null);
        }

        if (connectionDOList !=null && !connectionDOList.isEmpty()) {
            connectionMapper.insertBatch(connectionDOList);
        }


    }

    //获取坐标在手机屏幕内的所有站点信息
    @Override
    @Transactional
    public List<SimpleSiteRespVO> siteInScreen(String area){

        String[] split = area.split(":");
        String replace = split[1].replace("\"", "").replace("}","");


        long l = System.currentTimeMillis();
        //获取所有电站
        List<SiteDO> siteDOList = siteMapper.selectList();

        List<SiteDO> siteDOList1 = new ArrayList<>();
        //遍历电站
        for (SiteDO siteDO : siteDOList) {
            if (siteDO.getLatitudeLongitude() != null ) {
                //将电站中心点转化为double
                double[] pointDouble = convertStringToDoubleArray(siteDO.getLatitudeLongitude());
                //若电站在区域构成的最大四边形内并且在区域坐标集合内
                if(PolygonChecker.isPointInAnyPolygon(pointDouble,replace)){
                    siteDOList1.add(siteDO);
                }
            }
        }
        long l2 = System.currentTimeMillis();

        System.out.println("总时长：" + (l2 -l));
        return BeanUtils.toBean(siteDOList1,SimpleSiteRespVO.class);
    }


    //string转化为double[]，用于把site表中的中心坐标转化为方法可用数据类型
    public static double[] convertStringToDoubleArray(String input) {
        // 1. 预处理：去除空白字符和方括号
        String cleaned = input.replaceAll("\\s+", "")   // 移除所有空白字符
                .replaceAll("^\\[|\\]$", ""); // 移除开头和结尾的方括号

        // 2. 检查空字符串
        if (cleaned.isEmpty()) {
            return new double[0];
        }

        // 3. 分割字符串
        String[] parts = cleaned.split(",");
        double[] result = new double[parts.length];

        // 4. 转换每个部分
        for (int i = 0; i < parts.length; i++) {
            try {
                result[i] = Double.parseDouble(parts[i]);
            } catch (NumberFormatException e) {
                // 处理无效数值
                throw new IllegalArgumentException("无法解析的数值: '" + parts[i] +
                        "', 位置: " + i, e);
            }
        }

        return result;
    }

    @Override
    public List<AdminUserDO> getSiteRoleUser(List<Long> siteIds, Integer type) {
        List<AdminUserDO> userDOList = new ArrayList<>();
        Set<Long> longs = new HashSet<>();
        if(type !=null && type == 1){ //全职和兼职
            List<RoleDO> roleDOS = roleMapper.selectList(new LambdaQueryWrapper<RoleDO>().like(RoleDO::getCode, "full_").or().like(RoleDO::getCode, "part_"));
            if(roleDOS != null && !roleDOS.isEmpty()){
                for (RoleDO roleDO : roleDOS) {
                    longs.add(roleDO.getId());
                }
            }
        }else { //兼职
            List<RoleDO> roleDOS = roleMapper.selectList(new LambdaQueryWrapper<RoleDO>().like(RoleDO::getCode, "part_"));
            if(roleDOS != null && !roleDOS.isEmpty()){
                for (RoleDO roleDO : roleDOS) {
                    longs.add(roleDO.getId());
                }
            }
        }

        QueryWrapper<ConnectionDO> wrapper = new QueryWrapper<ConnectionDO>();
        wrapper.select("count(id)", "people_id")  // 选择统计值和分组字段
                .eq("type",2)          // WHERE type = 2
                .in("thing_id",siteIds)// WHERE thing_id IN (799,356,700)
                .groupBy("people_id")        // GROUP BY people_id
                .having("count(id) = {0}", siteIds.size());             // HAVING count = 3

        List<ConnectionDO> connectionDOS = connectionMapper.selectList(wrapper);
        if (connectionDOS!= null && !connectionDOS.isEmpty()) {
            List<Long> userIds = new ArrayList<>();
            for (ConnectionDO connectionDO : connectionDOS) {
                Long userId = connectionDO.getPeopleId();
                userIds.add(userId);
            }
            //过滤
            List<AdminUserDO> userList = adminUserService.getUserList(userIds);
            if(userList != null && !userList.isEmpty()){
                for (AdminUserDO adminUserDO : userList) {
                    List<UserRoleDO> userRoleDOS = userRoleMapper.selectListByUserIdAndRoleIdIds(adminUserDO.getId(),longs);
                    if(userRoleDOS != null && !userRoleDOS.isEmpty()){
                        userDOList.add(adminUserDO);
                    }
                }
            }
            return userDOList;
        }else {
            throw exception(SITE_NOT_PEOPLE);
        }
    }


    //String类型转化为List<Point2D.Double>
    public static List<Point2D.Double> convertStringToPointArray(String input) {
        // 1. 去除外层方括号
        String trimmed = input.replaceAll("\\s+", ""); // 移除所有空格
        if (trimmed.startsWith("[[")) {
            trimmed = trimmed.substring(2, trimmed.length() - 2);
        }

        // 2. 分割各个点字符串（分隔符为"],[")
        String[] pointStrings = trimmed.split("\\],\\[");

        // 3. 解析每个点字符串为Point2D.Double对象
        List<Point2D.Double> pointList = new ArrayList<>();
        for (String pointStr : pointStrings) {
            String[] coordinates = pointStr.split(",");
            if (coordinates.length != 2) {
                throw new IllegalArgumentException("无效的坐标格式: " + pointStr);
            }
            try {
                double x = Double.parseDouble(coordinates[0]);
                double y = Double.parseDouble(coordinates[1]);
                pointList.add(new Point2D.Double(x, y));
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException("坐标值非数字: " + pointStr, e);
            }
        }

        // 4. 转换为数组并返回
        return pointList;
    }






    //把String类型的数据转化为Point2D.Double
    public  Point2D.Double convertStringToPoint(String input) {
        // 1. 去除所有空格并验证格式
        String trimmed = input.replaceAll("\\s+", "");

        // 2. 移除首尾的方括号
        trimmed = trimmed.substring(1, trimmed.length() - 1);

        // 3. 按逗号分割字符串
        String[] coordinates = trimmed.split(",");
        if (coordinates.length != 2) {
            throw new IllegalArgumentException("坐标值数量错误，应为两个数值");
        }

        // 4. 转换为double类型
        try {
            double x = Double.parseDouble(coordinates[0]);
            double y = Double.parseDouble(coordinates[1]);
            return new Point2D.Double(x, y);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("坐标值非数字", e);
        }
    }



    //判断一点是否在多边形的区域内
    public  Boolean isInArea(List<Point2D.Double> pointList, Point2D.Double point) {

        List<Point2D.Double> points;

        Boolean flag = true; //是否在区域内标识
        Point2D.Double p, p1, p2;
        Integer across = 0; //穿越次数
        double precision = 2e-10; //浮点类型计算时候的比较容差
        p = point;

        for (int i = 0; i < pointList.size(); i++) {
            p1 = pointList.get(i);
            int j = (i + 1) >= pointList.size() ? 0 : (i + 1);
            p2 = pointList.get(j);
            // 1、判断是否在点上
            if (p1.equals(p) || p2.equals(p)) {
                return flag;
            }
            // 2、该点是否在两个端点之间
            if (p.y <= Math.max(p1.y, p2.y) && p.y >= Math.min(p1.y, p2.y)) {
                // 3、判断该点是否在两点连成的线段上
                if (p.x <= Math.max(p1.x, p2.x) && p.x >= Math.min(p1.x, p2.x)) {
                    // 其一：该线段是水平线
                    if (p1.y == p2.y) {
                        if (p.y == p1.y) {
                            return flag;
                        }
                    }
                    // 其二：该线段是垂直线
                    if (p1.x == p2.x) {
                        if (p.x == p1.x) {
                            return flag;
                        }
                    }
                    // 其三：该线段是斜线
                    double xianShangY = p1.y + (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x);
                    if (Math.abs(xianShangY - p.y) < precision) {
                        // 在线上
                        return flag;
                    }
                }
                // 4、判断两个端点是否越过该点（因为是左水平射线）
                if (p.x <= Math.min(p1.x, p2.x)) {
                    continue;
                }
               /*
                    该点位于两个端点之间，判断是否穿过顶点（穿过顶点时，顶点按照在射线上部处理）
                    穿过顶点时，只有两个端点在射线两侧的才按照穿越处理
                */
                if (p1.y != p2.y && p.y != Math.min(p1.y, p2.y)) {
                    across++;
                }
            }
        }
        if (across % 2 == 0) {
            // 偶数，在外部
            return !flag;
        }
        return flag;
    }

    //判断电站是否在该区域最大四边形形范围之内
    public Boolean AreaMetadata(List<Point2D.Double> polygon,Point2D.Double p) {

        // 计算包围盒
        Double minX = polygon.stream().mapToDouble(a -> a.x).min().getAsDouble();
        Double maxX = polygon.stream().mapToDouble(b -> b.x).max().getAsDouble();
        Double minY = polygon.stream().mapToDouble(c -> c.y).min().getAsDouble();
        Double maxY = polygon.stream().mapToDouble(d -> d.y).max().getAsDouble();

        return p.x >= minX && p.x <= maxX && p.y >= minY && p.y <= maxY;
    }


    //获取电站是商机数量


    //获取本月和上月的商机增长比值
    @Override
    public Map<Object,Object> growthGate(SitePageReqVO pageReqVO){

        Map<Object,Object> map = new HashMap<>();

        pageReqVO.setSiteStatus(OPPORTUNITY.getCode());
        List<SiteRespVO> siteList = getSiteList(pageReqVO);



        /*List<Long> siteIds = siteList.stream()
                .map(SiteRespVO::getId)
                .collect(Collectors.toList());

        // 计算当前日期和昨天的日期
        LocalDate now = LocalDate.now();
        LocalDate yesterday = now.minusDays(1);

// 构建单一查询获取所有需要的时间范围数据
        List<SiteDO> allSites = siteMapper.selectList(
                new LambdaQueryWrapper<SiteDO>()
                        .in(SiteDO::getId, siteIds)
                        .and(qw -> qw
                                .between(
                                        SiteDO::getBusinessTime,
                                        yesterday.atStartOfDay(),
                                        yesterday.atTime(LocalTime.MAX)
                                )
                                .or()
                                .between(
                                        SiteDO::getBusinessTime,
                                        now.atStartOfDay(),
                                        now.atTime(LocalTime.MAX)
                                )
                        )
        );

// 使用流分组代替两次查询
        Map<LocalDate, List<SiteDO>> dateGrouped = allSites.stream()
                .collect(Collectors.groupingBy(
                        site -> site.getBusinessTime().toLocalDate()
                ));

        List<SiteDO> siteDOListLast = dateGrouped.getOrDefault(yesterday, Collections.emptyList());
        List<SiteDO> siteDOListNow = dateGrouped.getOrDefault(now, Collections.emptyList());*/


        //获取本月和上月的月份
//        SitePageReqVO pageReqVO2 = new SitePageReqVO();
//
//        LocalDate now = LocalDate.now();
//        Integer month1 =now.getMonth().getValue();
//        Integer year1 = now.getYear();
//
//        Integer year2 = 0;
//        Integer month2 = 1;
//
//        if (month1 == 1) {
//            month2 = 12;
//            year2 = year1 - 1;
//        }else {
//            month2 = month1 - 1;
//            year2 = year1;
//        }
//        //获取当月的开始时间和结束时间
//        YearMonth targetMonth1 = YearMonth.of(year1, month1);
//
//        // 当月起始时间（首日00:00:00）
//        LocalDateTime start1 = targetMonth1.atDay(1).atStartOfDay();
//
//        // 当月结束时间（末日23:59:59.999999999）
//        LocalDateTime end1 = targetMonth1.atEndOfMonth()
//                .atTime(23, 59, 59, 999_999_999);
//        LocalDateTime[] localDateTimes1 = new LocalDateTime[]{start1,end1};
//
//        //获取上个月的开始时间和结束时间
//        YearMonth targetMonth2 = YearMonth.of(year2,month2);
//        LocalDateTime start2 = targetMonth2.atDay(1).atStartOfDay();
//        LocalDateTime end2 = targetMonth2.atEndOfMonth()
//                .atTime(23, 59, 59, 999_999_999);
//        LocalDateTime[] localDateTimes2 = new LocalDateTime[]{start2,end2};
//
//        //获取电站
//        pageReqVO1.setBusinessTime(localDateTimes1);
//        pageReqVO1.setSiteStatus(OPPORTUNITY.getCode());
//
//        pageReqVO2.setBusinessTime(localDateTimes2);
//        pageReqVO2.setSiteStatus(OPPORTUNITY.getCode());
//
/*        //获取本月和上月的更新的状态为商机的电站
        int size1 = siteDOListNow.size();
        int size2 = siteDOListLast.size();*/

        /*double i = 0;
        if (size2 == 0) {
            i = size1;
        }else {
            i = (double) (size1 - size2) / size2;
        }*/
        map.put(7,siteList.size());
/*        map.put(8,i);*/

        return map;
    }


    //转为Point。2D类型的数据
    public static Point2D.Double convert(String coordinateStr) {
        // 1. 去除字符串两端的方括号和空格
        String cleanedStr = coordinateStr
                .replace("[", "")
                .replace("]", "")
                .trim();

        // 2. 按逗号分割成两部分
        String[] parts = cleanedStr.split(",");
        if (parts.length != 2) {
            throw new IllegalArgumentException("输入格式无效，应该是 [经度, 纬度] 格式: " + coordinateStr);
        }

        // 3. 分别转换为双精度数值
        try {
            double longitude = Double.parseDouble(parts[0].trim());
            double latitude = Double.parseDouble(parts[1].trim());

            // 4. 创建并返回 Point2D.Double 对象
            return new Point2D.Double(longitude, latitude);

        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("坐标值必须是有效的数字: " + coordinateStr, e);
        }
    }




    //构建数组
    public static String generateGeoSquare(double centerLon, double centerLat, double sideLength) {
        // 计算四个角的坐标
        double[][] corners = calculateSquareCorners(centerLon, centerLat, sideLength);

        // 构建结果字符串
        StringBuilder result = new StringBuilder();

        // 第二种数据：四个角点
        result.append("\t[");
        for (int i = 0; i < corners.length; i++) {
            if (i > 0) result.append(",");
            result.append("[").append(df.format(corners[i][0]))
                    .append(",").append(df.format(corners[i][1])).append("]");
        }
        result.append("]");

        return result.toString();
    }

    /**
     * 计算以给定中心点为中心的正方形的四个角坐标
     */
    public static double[][] calculateSquareCorners(double centerLon, double centerLat, double sideLength) {
        // 计算对角线长度（米） - 正方形的对角线
        double diagonal = sideLength * Math.sqrt(2);

        // 计算四个方向的角度（相对于正北）
        double[] bearings = {315, 45, 135, 225}; // 西北、东北、东南、西南

        double[][] corners = new double[4][2];

        for (int i = 0; i < 4; i++) {
            Point2D.Double point = calculateDestinationPoint(
                    centerLon, centerLat, diagonal/2, bearings[i]
            );
            corners[i][0] = point.x; // 经度
            corners[i][1] = point.y; // 纬度
        }

        return corners;
    }

    /**
     * 根据起点、距离和方向计算终点坐标
     */
    public static Point2D.Double calculateDestinationPoint(double startLon, double startLat,
                                                           double distance, double bearing) {
        // 将角度转换为弧度
        double startLatRad = Math.toRadians(startLat);
        double bearingRad = Math.toRadians(bearing);

        // 角距离（弧度）
        double angularDistance = distance / EARTH_RADIUS;

        // 计算终点的纬度
        double endLatRad = Math.asin(Math.sin(startLatRad) * Math.cos(angularDistance) +
                Math.cos(startLatRad) * Math.sin(angularDistance) * Math.cos(bearingRad));

        // 计算终点的经度
        double endLonRad = Math.atan2(
                Math.sin(bearingRad) * Math.sin(angularDistance) * Math.cos(startLatRad),
                Math.cos(angularDistance) - Math.sin(startLatRad) * Math.sin(endLatRad)
        ) + Math.toRadians(startLon);

        // 转换为度
        double endLat = Math.toDegrees(endLatRad);
        double endLon = Math.toDegrees(endLonRad);

        return new Point2D.Double(endLon, endLat);
    }


    //判断中心点坐标是否合法
    public static boolean isValidLatitudeLongitude(String string){

        String input = string.replace(" ", "");

        if (!input.startsWith("[") || !input.endsWith("]")) {
            return false;
        }

        // 移除方括号获取内容
        String content = input.substring(1, input.length() - 1);

        // 分割逗号两侧的内容
        String[] parts = content.split(",");
        if (parts.length != 2) {
            return false;
        }

        // 尝试解析经度
        try {
            double longitude = Double.parseDouble(parts[0]);
            if (longitude < -180 || longitude > 180) {
                return false;
            }
        } catch (NumberFormatException e) {
            return false;
        }

        // 尝试解析纬度
        try {
            double latitude = Double.parseDouble(parts[1]);
            if (latitude < -90 || latitude > 90) {
                return false;
            }
        } catch (NumberFormatException e) {
            return false;
        }

        return true;
    }



}
